﻿#region Header
// Copyright 2007-2011, Jerónimo Milea
// 
// This file is part of NetJsWire.
// 
//     NetJsWire is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
// 
//     NetJsWire is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
// 
//     You should have received a copy of the GNU General Public License
//     along with NetJsWire.  If not, see <http://www.gnu.org/licenses/>.
#endregion

using System;
using System.ComponentModel;
using System.Windows.Forms;
using NetJsWire.JsonRpcHandler;

namespace NetJsWire.Widgets.Config
{
    [Serializable]
    public class BoxComponentConfigOptions : ComponentConfigOptions
    {
        private string _anchor;

        private bool _autoHeight;

        private bool _autoScroll;

        private bool _autoWidth;

        private int? _boxMaxHeight;

        private int? _boxMaxWidth;

        private int? _boxMinHeight;

        private int? _boxMinWidth;

        private double _flex;

        private Padding _margins = Padding.Empty;

        private string _region;

        /// <summary>
        ///   Default constructor
        /// </summary>
        /// <param name = "ownerWidget">The owner of this configuration</param>
        public BoxComponentConfigOptions( IWidget ownerWidget )
            : base( ownerWidget )
        {
        }

        /// <summary>
        ///   <b>Note</b>: this config is only used when this Component is rendered by a Container which has been configured to use an AnchorLayout based layout manager, for example:
        ///   Ext.form.FormPanel
        ///   specifying <c>layout: 'anchor' // or 'form', or 'absolute'</c>
        ///   See <c>Ext.layout.AnchorLayout.anchor</c> also.
        /// </summary>
        [Description( "This config is only used when this Component is rendered by a Container which has been configured to use an AnchorLayout based layout manager" )]
        [DefaultValue( ( string ) null )]
        [Browsable( true )]
        public override string Anchor
        {
            get { return _anchor; }
            set
            {
                SetValue( "anchor", value, null, _anchor );
                _anchor = value;
            }
        }

        /// <summary>
        ///   true to use height:'auto', false to use fixed height (defaults to false).
        ///   <remarks>
        ///     Although many components inherit this config option, not all will function as expected with a height of 'auto'. Setting autoHeight:true means 
        ///     that the browser will manage height based on the element's contents, and that Ext will not manage it at all.
        ///     If the browser is managing the height, be aware that resizes performed by the browser in response to changes within the structure of the 
        ///     Component cannot be detected. Therefore changes to the height might result in elements needing to be synchronized with the new height. Example:
        ///     <example>
        ///       <code>
        ///         var w = new Ext.Window({
        ///         title: 'Window',
        ///         width: 600,
        ///         autoHeight: true,
        ///         items: {
        ///         title: 'Collapse Me',
        ///         height: 400,
        ///         collapsible: true,
        ///         border: false,
        ///         listeners: {
        ///         beforecollapse: function() {
        ///         w.el.shadow.hide();
        ///         },
        ///         beforeexpand: function() {
        ///         w.el.shadow.hide();
        ///         },
        ///         collapse: function() {
        ///         w.syncShadow();
        ///         },
        ///         expand: function() {
        ///         w.syncShadow();
        ///         }
        ///         }
        ///         }
        ///         }).show();
        ///       </code>
        ///     </example>
        ///   </remarks>
        /// </summary>
        [Description( "true to use height:'auto', false to use fixed height (defaults to false)." )]
        [DefaultValue( false )]
        [Browsable( true )]
        public override bool AutoHeight
        {
            get { return _autoHeight; }
            set
            {
                SetValue( "autoHeight", value, false, _autoHeight );
                _autoHeight = value;
            }
        }

        /// <summary>
        ///   true to use overflow:'auto' on the components layout element and show scroll bars automatically when necessary, false to clip any overflowing content (defaults to false).
        /// </summary>
        [Description( "true to use overflow:'auto' on the components layout element and show scroll bars automatically when necessary, false to clip any overflowing content (defaults to false)." )]
        [DefaultValue( false )]
        [Browsable( true )]
        public override bool AutoScroll
        {
            get { return _autoScroll; }
            set
            {
                SetValue( "autoScroll", value, false, _autoScroll );
                _autoScroll = value;
            }
        }

        /// <summary>
        ///   True to use width:'auto', false to use fixed width (or allow it to be managed by its parent Container's layout manager. Defaults to false.
        ///   <remarks>
        ///     Although many components inherit this config option, not all will function as expected with a width of 'auto'. Setting autoWidth:true means 
        ///     that the browser will manage width based on the element's contents, and that Ext will not manage it at all.
        ///     If the browser is managing the width, be aware that resizes performed by the browser in response to changes within the structure of the Component 
        ///     cannot be detected. Therefore changes to the width might result in elements needing to be synchronized 
        ///     with the new width. For example, where the target element is:
        ///     <code>
        ///       <![CDATA[<div id='grid-container' style='margin-left:25%;width:50%'></div>]]>
        ///     </code>
        ///     A Panel rendered into that target element must listen for browser window resize in order to relay its child items when the browser changes its width:
        ///     <code>
        ///       var myPanel = new Ext.Panel({
        ///       renderTo: 'grid-container',
        ///       monitorResize: true, // relay on browser resize
        ///       title: 'Panel',
        ///       height: 400,
        ///       autoWidth: true,
        ///       layout: 'hbox',
        ///       layoutConfig: {
        ///       align: 'stretch'
        ///       },
        ///       defaults: {
        ///       flex: 1
        ///       },
        ///       items: [{
        ///       title: 'Box 1',
        ///       }, {
        ///       title: 'Box 2'
        ///       }, {
        ///       title: 'Box 3'
        ///       }],
        ///       });
        ///     </code>
        ///   </remarks>
        /// </summary>
        [Description( "True to use width:'auto', false to use fixed width (or allow it to be managed by its parent Container's layout manager. Defaults to false." )]
        [DefaultValue( false )]
        [Browsable( true )]
        public override bool AutoWidth
        {
            get
            {
                return _autoWidth;
            }
            set
            {
                SetValue( "autoWidth", value, false, _autoWidth );
                _autoWidth = value;
            }
        }

        /// <summary>
        ///   The maximum value in pixels which this BoxComponent will set its height to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Description( "The maximum value in pixels which this BoxComponent will set its height to." )]
        [DefaultValue( null )]
        [Browsable( true )]
        public override int? BoxMaxHeight
        {
            get { return _boxMaxHeight; }
            set
            {
                SetValue( "boxMaxHeight", value, null, _boxMaxHeight );
                _boxMaxHeight = value;
            }
        }

        /// <summary>
        ///   The maximum value in pixels which this BoxComponent will set its width to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Description( "The maximum value in pixels which this BoxComponent will set its width to." )]
        [DefaultValue( null )]
        [Browsable( true )]
        public override int? BoxMaxWidth
        {
            get { return _boxMaxWidth; }
            set
            {
                SetValue( "boxMaxWidth", value, null, _boxMaxWidth );
                _boxMaxWidth = value;
            }
        }

        /// <summary>
        ///   The minimum value in pixels which this BoxComponent will set its height to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Description( "The minimum value in pixels which this BoxComponent will set its height to." )]
        [DefaultValue( null )]
        [Browsable( true )]
        public override int? BoxMinHeight
        {
            get { return _boxMinHeight; }
            set
            {
                SetValue( "boxMinHeight", value, null, _boxMinHeight );
                _boxMinHeight = value;
            }
        }

        /// <summary>
        ///   The minimum value in pixels which this BoxComponent will set its width to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Description( "The minimum value in pixels which this BoxComponent will set its width to." )]
        [DefaultValue( null )]
        [Browsable( true )]
        public override int? BoxMinWidth
        {
            get { return _boxMinWidth; }
            set
            {
                SetValue( "boxMinWidth", value, null, _boxMinWidth );
                _boxMinWidth = value;
            }
        }

        /// <summary>
        ///   <b>Note: this config is only used when this Component is rendered by a Container which has been configured to use a BoxLayout.</b>
        ///   Each child Component with a flex property will be flexed either vertically (by a VBoxLayout) or horizontally (by an HBoxLayout) according to the item's relative flex value compared to the sum of all Components with flex value specified. Any child items that have either a flex = 0 or flex = undefined will not be 'flexed' (the initial size will not be changed).
        /// </summary>
        [Description( "Each child Component with a flex property will be flexed either vertically (by a VBoxLayout) or horizontally (by an HBoxLayout) according to the item's relative flex value compared to the sum of all Components with flex value specified." )]
        [DefaultValue( 0D )]
        [Browsable( true )]
        public override double Flex
        {
            get { return _flex; }
            set
            {
                SetValue( "flex", value, 0D, _flex );
                _flex = value;
            }
        }

        /// <summary>
        ///   An object containing margins to apply to this BoxComponent in the format:
        ///   E.g.:
        ///   <code>
        ///     {
        ///     top: (top margin),
        ///     right: (right margin),
        ///     bottom: (bottom margin),
        ///     left: (left margin)
        ///     }
        ///   </code>
        ///   <remarks>
        ///     this config is only used when this BoxComponent is rendered by a Container which has been configured to use the 
        ///     BorderLayout or one of the two BoxLayout subclasses.
        ///   </remarks>
        ///   May also be a string containing space-separated, numeric margin values. The order of the sides associated with each value matches the way CSS processes margin values:
        ///   <list type = "bullet">
        ///     <item>
        ///       If there is only one value, it applies to all sides.
        ///     </item>
        ///     <item>
        ///       If there are two values, the top and bottom borders are set to the first value and the right and left are set to the second.
        ///     </item>
        ///     <item>
        ///       If there are three values, the top is set to the first value, the left and right are set to the second, and the bottom is set to the third.
        ///     </item>
        ///     <item>
        ///       If there are four values, they apply to the top, right, bottom, and left, respectively.
        ///     </item>
        ///   </list>
        ///   Defaults to:
        ///   <code>
        ///     {top:0, right:0, bottom:0, left:0}
        ///   </code>
        /// </summary>
        [Description( "An object containing margins to apply to this BoxComponent." )]
        [Browsable( true )]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
        //[TypeConverter( typeof( ThicknessConverter ) )]
        [TypeConverterAttribute( typeof( PaddingConverter ) )]
        [DefaultValue( typeof( Padding ), "0, 0, 0, 0" )]
        public override Padding Margins
        {
            get { return _margins; }
            set
            {
                SetValue( "margins", value, null, _margins );
                _margins = value;
            }
        }

        /// <summary>
        ///   The region this Component represents in a BorderLayout.
        /// </summary>
        /// <remarks>
        ///   This config is only used when this BoxComponent is rendered by a Container which has been configured to use the BorderLayout layout manager 
        ///   (e.g. specifying layout:'border').
        /// </remarks>
        [Description( "The region this Component represents in a BorderLayout." )]
        [DefaultValue( ( string ) null )]
        [Browsable( true )]
        public override string Region
        {
            get { return _region; }
            set
            {
                SetValue( "region", value, null, _region );
                _region = value;
            }
        }

        public bool ShouldSerializeMargins()
        {
            return Margins != Padding.Empty && Margins.All != 0;
        }
    }
}
